/*!
//      
//      \file	k2k_StateMachine.h
//      
//      \author	Copyright 2010 Valentina Vuksic <vuksv1@bfh.ch>, Beat Liechti <liecb2@bfh.ch>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.
//
//		Abstract Data Type for state machine
//      
//      \brief		CAS-EBX-03 Projektarbeit 
//      			Valentina Vuksic (VUKSV1), Beat Liechti (LIECB2)
//      			StateMachine ADT for the k2k (Kaffee2000) application
//      \version	1.0
//      \date		2010-04-11
//      \remark		Last Modifications:
//      \remark  	v1.0, VUKSV1/LIECB2, 2010-04-11 Initial release
//
*/

#ifndef __k2k_StateMachine__
#define __k2k_StateMachine__

#include <stdlib.h>
#include <signal.h>

#include "k2k_GlobalTypes.h"
#include "k2k_StateMachineTypes.h"
#include "k2k_Signal.h"

/*!
// k2k_StateMachine defines the data structure for the ADT 
// \brief k2k_StateMachine stuct type for ADT
*/				
typedef struct k2k_StateMachine_Struct
{	
	/*! previous state */
	k2k_State previousState;
	/*! current state */
	k2k_State currentState;
	/*! state handler functions*/
	k2k_StateHandlerFunc stateHandlers[STATE_MAX];
	/*! state handler data */
	k2k_StateHandlerData *handlerData[STATE_MAX];
	/*! Nano X ADT */
	k2k_NanoX *nanoX;
	/*! file descriptor for coffee grinder engine */
	int fd_coffgrn;
	/*! file descriptor for milk pump */
	int fd_milkpmp;
    /*! helper ADT for signaling SIGCHLD */
    k2k_Signal *signalChld;
    /*! error code to signal initialization errors */
	int err;
} k2k_StateMachine;

/*!
//
// Creates StateMachine ADT "object"
// 
// \return pointer to the StateMachine ADT
//
*/
k2k_StateMachine* k2k_StateMachine_Create(k2k_NanoX *nanoX);

/*!
//
// Releases StateMachine ADT "object"
// 
// \param stateMachine is the pointer to the StateMachine structure
// 
// \return noting
//
*/
void k2k_StateMachine_Release(k2k_StateMachine *stateMachine);

/*!
//
// Forward events to the state machine
// 
// \param stateMachine is the pointer to the StateMachine structure
// \param event describes the event
// 
// \return new state of the state machine
//
*/
k2k_State k2k_StateMachine_ProcessEvent(k2k_StateMachine *stateMachine, k2k_Event event);

/*!
//
// Adds a state handler
// 
// \param stateMachine is the pointer to the StateMachine structure
// \param state describes the state for which the handler is called
// \param handlerFunc is the pointer to the function to handle the state
// \param handlerData is the pointer to custom data (typically the corresponding ADT struct)
// 
// \return nothing
//
*/
void k2k_StateMachine_AddStateHandler(k2k_StateMachine *stateMachine, k2k_State state, k2k_StateHandlerFunc handlerFunc, k2k_StateHandlerData *handlerData);

/*!
//
// Set the speed of the coffee grinder 
// 
// \param speed
// 
// \return nothing
//
*/
void k2k_StateMachine_SetGrinderSpeed(k2k_StateMachine *stateMachine, int speed);

/*!
//
// Set the amount pumped by the milk pump 
// 
// \param amount
// 
// \return nothing
//
*/
void k2k_StateMachine_SetMilkPumpAmount(k2k_StateMachine *stateMachine, int amount);

/*!
//
// Increment the persistang coffee counter 
// 
// \param nothing
// 
// \return nothing
//
*/
void k2k_StateMachine_CountOneCoffee(void);

/*!
//
// Checks whether cleaning is required: a certain number of coffee`s has been made. 
// 
// \param nothing
// 
// \return true if cleaning is required, false otherwise
//
*/
BOOL k2k_StateMachine_IsCleaningRequired(void);

/*!
//
//  Reset the persistant coffee counter
// 
// \param nothing
// 
// \return nothing
//
*/
void k2k_StateMachine_ResetCoffeeCount(void);

#endif
